/***************************************************************************
 *   This file is a part of match.                               *
 *   Copyright (C) 2009 by fu4ny 										   *
 *   ntcong.it@gmail.com                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      * 
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>   *             *
 ***************************************************************************/

#include "SurfDB.h"
#include <fstream>
#include <iostream>
#include "common/Command.h"
using namespace std;

SurfDB::SurfDB() {
	dimension = 0;
	numberOfVector = 0;
}


void SurfDB::load(const char *filename) {
	ifstream ifs(filename);
	if ( !ifs.good() ) {
		cerr << "Cannot open "<< filename << " for reading!\n";
		return;
	}
	int newDim, newSize;
	ifs >> newDim >> newSize;
	if ( newDim != dimension ) {
			if ( dimension == 0 ) dimension = newDim;
			else {
				cerr << "Incompatible SURF file format!\n";
				return;
			}
		}
	for (int i = 0; i < newSize; i++) {
		IPoint newPoint;
		ifs >> newPoint.obj_id >> newPoint.pose >> newPoint.vector_number;
		newPoint.vectorList.clear();
		newPoint.vectorList.resize( dimension );
		for (int j = 0; j < dimension - 1; j++)
			ifs >> newPoint.vectorList[j];
		list.push_back( newPoint );
		numberOfVector++;
	}
	ifs.close();
}

void SurfDB::write( const char* filename ) {
	ofstream ofs( filename );
	if ( !ofs ) {
		cerr << "Cannot open " << filename << " for writing\n";
		return;
	}
	ofs << dimension << endl << numberOfVector << endl;
	for (int i = 0; i < numberOfVector; i++ ) {
		ofs << list[i].obj_id << " " << list[i].pose << " " << list[i].vector_number << " ";
		for (int j=0; j < dimension-1; j++ ) {
			ofs << list[i].vectorList[j] << " ";
		}
		ofs << endl;
	}
	ofs.close();
}

int SurfDB::size() {
	return numberOfVector;
}

int SurfDB::dim() {
	return dimension;
}

void SurfDB::loadCom(const char *filename, double obj_id, double pose) {
	ifstream ifs(filename);
	if ( !ifs.good() ) {
		cerr << "Cannot open "<< filename << " for reading!\n";
		return;
	}
	int newSize,newDim;
	ifs >> newDim >> newSize;
	if ( newDim != dimension ) {
		if ( dimension == 0 ) dimension = newDim;
		else {
			cerr << "Incompatible SURF file format!\n";
			return;
		}
	}
	int count=0;
	for (int i = 0; i < newSize; i++) {
		IPoint newPoint;
		double temp;
		//Ignore a b x y z and lap, ugly way but since we don't use it...
		ifs >> temp >> temp >> temp >> temp >> temp >> temp;
		newPoint.obj_id = obj_id;
		newPoint.pose = pose;
		newPoint.vector_number = ++count;
		newPoint.vectorList.clear();
		newPoint.vectorList.resize(dimension);
		for (int j = 0; j < dimension - 1; j++)
			ifs >> newPoint.vectorList[j];
		list.push_back(newPoint);
		numberOfVector++;
	}
	ifs.close();
}

void SurfDB::remove( double id, double pose ) {
	int count=0;
	for (int i=0; i<numberOfVector; i++ )
		if ( list[i].obj_id == id )
			if ( list[i].pose == pose ) {
				count++;
				list.erase(list.begin()+i);
			}
	numberOfVector -= count;
}

void SurfDB::addImg( const char* filename, int width, int height ) {
	//I can't implement Surf generator here, so we must use shell to generate it
	//TODO:We should check if we can execute "convert" and "rm"
	//rm is not a big problem, but convert is
	//surf.ln can be check by having a file checker function.
	Command cmd;
	cmd << "convert " << filename << " -resize " << width << "x" << height << " " << filename << ".jpg";
	cmd.exec();
	cmd << "convert " << filename <<  ".jpg " << filename << ".pgm";
	cmd.exec();
	cmd << "./surf.ln -i " << filename << ".pgm -o " <<  filename << ".surf -q";
	cmd.exec();
	string name(filename);
	name += ".surf";
	load(name.c_str());
	cmd << "rm -f " <<  filename << ".*";//Safely delelte all files except the image.
	cmd.exec();
}

void SurfDB::addImg( const char* filename ) {
	//For now the maximum image size we accept is 1024x768,
	//so if you do not provide the size, we resize it to 1024x768
	addImg( filename, 1024, 768 );

}

SurfDB::~SurfDB() {

}
